package com.cyzy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cyzy.dto.SignInDto;
import com.cyzy.dto.SignInResultDto;
import com.cyzy.mapper.SignInMapper;
import com.cyzy.mapper.UserMapper;
import com.cyzy.pojo.SignIn;
import com.cyzy.pojo.User;
import com.cyzy.service.SignInService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

@Service
public class SignInServiceImpl implements SignInService {
    
    @Autowired
    private SignInMapper signInMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    private static final int SIGN_IN_POINTS = 10; // 签到获得的积分
    
    @Override
    public SignInDto getSignInInfo(Long userId) {
        // 获取用户的签到记录
        QueryWrapper<SignIn> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("signin_user_id", userId);
        queryWrapper.orderByDesc("signin_date");
        List<SignIn> signInList = signInMapper.selectList(queryWrapper);
        
        SignInDto signInDto = new SignInDto();
        LocalDate today = LocalDate.now();
        signInDto.setCurrentYear(today.getYear());
        signInDto.setCurrentMonth(today.getMonthValue());
        
        if (signInList.isEmpty()) {
            // 没有签到记录
            signInDto.setTotalDays(0);
            signInDto.setCurrentMonthDays(0);
            signInDto.setConsecutiveDays(0);
            signInDto.setTodaySigned(false);
            signInDto.setSignedDates(new ArrayList<>());
            return signInDto;
        }
        
        // 获取最新的签到记录
        SignIn latestSignIn = signInList.get(0);
        signInDto.setTotalDays(latestSignIn.getSigninCumulative());
        
        // 重新计算本月签到天数（因为可能跨月了）
        int currentMonthDays = 0;
        for (SignIn signIn : signInList) {
            LocalDate signDate = signIn.getSigninDate().toLocalDateTime().toLocalDate();
            if (signDate.getYear() == today.getYear() && signDate.getMonthValue() == today.getMonthValue()) {
                currentMonthDays++;
            }
        }
        signInDto.setCurrentMonthDays(currentMonthDays);
        signInDto.setConsecutiveDays(latestSignIn.getSigninStreak());
        
        // 检查今天是否已签到
        LocalDate latestSignInDate = latestSignIn.getSigninDate().toLocalDateTime().toLocalDate();
        signInDto.setTodaySigned(latestSignInDate.equals(today));
        
        // 获取所有签到日期
        List<String> signedDates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (SignIn signIn : signInList) {
            LocalDate signDate = signIn.getSigninDate().toLocalDateTime().toLocalDate();
            signedDates.add(signDate.format(formatter));
        }
        signInDto.setSignedDates(signedDates);
        
        return signInDto;
    }
    
    @Override
    @Transactional
    public SignInResultDto signIn(Long userId) {
        SignInResultDto result = new SignInResultDto();
        LocalDate today = LocalDate.now();
        
        // 检查今天是否已经签到
        QueryWrapper<SignIn> todayQuery = new QueryWrapper<>();
        todayQuery.eq("signin_user_id", userId);
        todayQuery.apply("DATE(signin_date) = {0}", today.toString());
        SignIn todaySignIn = signInMapper.selectOne(todayQuery);
        
        if (todaySignIn != null) {
            result.setSuccess(false);
            result.setMessage("今日已签到");
            result.setEarnedPoints(0);
            result.setSignInInfo(getSignInInfo(userId));
            return result;
        }
        
        // 获取最新的签到记录
        QueryWrapper<SignIn> latestQuery = new QueryWrapper<>();
        latestQuery.eq("signin_user_id", userId);
        latestQuery.orderByDesc("signin_date");
        latestQuery.last("LIMIT 1");
        SignIn latestSignIn = signInMapper.selectOne(latestQuery);
        
        // 计算签到数据
        int cumulativeDays = 1;
        int monthlyDays = 1;
        int streakDays = 1;
        
        if (latestSignIn != null) {
            LocalDate lastSignDate = latestSignIn.getSigninDate().toLocalDateTime().toLocalDate();
            cumulativeDays = latestSignIn.getSigninCumulative() + 1;
            
            // 计算本月签到天数
            if (lastSignDate.getYear() == today.getYear() && lastSignDate.getMonthValue() == today.getMonthValue()) {
                monthlyDays = latestSignIn.getSigninMonthly() + 1;
            } else {
                monthlyDays = 1; // 新月份，重新开始计算
            }
            
            // 计算连续签到天数
            long daysBetween = ChronoUnit.DAYS.between(lastSignDate, today);
            if (daysBetween == 1) {
                // 连续签到
                streakDays = latestSignIn.getSigninStreak() + 1;
            } else {
                // 中断了，重新开始
                streakDays = 1;
            }
        }
        
        // 插入新的签到记录
        SignIn newSignIn = new SignIn();
        newSignIn.setSigninUserId(userId.intValue());
        newSignIn.setSigninCumulative(cumulativeDays);
        newSignIn.setSigninMonthly(monthlyDays);
        newSignIn.setSigninStreak(streakDays);
        newSignIn.setSigninDate(Timestamp.valueOf(LocalDateTime.now()));
        
        signInMapper.insert(newSignIn);
        
        // 更新用户积分
        User user = userMapper.selectById(userId);
        if (user != null) {
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("user_id", userId);
            updateWrapper.set("user_score", user.getUserScore() + SIGN_IN_POINTS);
            userMapper.update(null, updateWrapper);
        }
        
        // 返回结果
        result.setSuccess(true);
        result.setMessage("签到成功！获得" + SIGN_IN_POINTS + "积分奖励");
        result.setEarnedPoints(SIGN_IN_POINTS);
        result.setSignInInfo(getSignInInfo(userId));
        
        return result;
    }
}
